using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Miao.Unity.SceneManagement
{
    /// <summary>
    /// Represents an opened game scene.
    /// This type is a high-level wrapper for <see cref="Scene"/>.
    /// </summary>
    public abstract class GameScene
    {
        public bool activated => SceneManager.GetActiveScene() == scene;
        public bool closed { get; private set; }

        public abstract Scene scene { get; }

        public static async Task<GameScene> Load(string name, LoadSceneMode loadSceneMode = LoadSceneMode.Single)
        {
#if UNITY_2023_2_OR_NEWER
            await SceneManager.LoadSceneAsync(name, loadSceneMode);
#else
            TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
            SceneManager.LoadSceneAsync(name, loadSceneMode).completed += _ => taskCompletionSource.SetResult(true);
            await taskCompletionSource.Task;
#endif
            return new StandardScene(SceneManager.GetSceneByName(name));
        }
        public static GameScene Create(string name)
        {
            return new StandardScene(SceneManager.CreateScene(name));
        }

        public void GetRootGameObjects(List<GameObject> rootGameObjectList)
        {
            scene.GetRootGameObjects(rootGameObjectList);
        }
        public Task Close()
        {
            if (closed) return Task.CompletedTask;
            closed = true;
            return OnClose();
        }
        public void Activate()
        {
            if (activated || closed) return;
            SceneManager.SetActiveScene(scene);
        }

        protected abstract Task OnClose();
    }
}